package org.web.clientlistmanager.server.biz;

import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.web.clientlistmanager.sdk.dto.ClmRequest;
import org.web.clientlistmanager.sdk.event.EventEnum;
import org.web.clientlistmanager.sdk.event.EventHelper;
import org.web.clientlistmanager.sdk.event.EventInterface;
import org.web.clientlistmanager.server.domain.ClientProcessDO;
import org.web.clientlistmanager.server.domain.query.QueryClientProcess;
import org.web.clientlistmanager.server.service.ClientProcessService;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service("clmHeartbeatEvent")
public class ClmHeartBeatEvent implements EventInterface {

    private static final Logger logger = Logger.getLogger(ClmHeartBeatEvent.class);

    private final ConcurrentHashMap<String, Long> lastHeartbeatMap = new ConcurrentHashMap<>();

    @Resource
    private ClientProcessService clientProcessService;

    /**
     * 5秒保护，5秒以内的都不处理。
     */
    private static final Long IGNORE_TIME = 5 * 1000L;

    /**
     * 超60秒内的清除缓存。
     */
    private static final Long REMOVE_TIME = 60 * 1000L;

    @Override
    public void executeRequest(ClmRequest clmRequest, ChannelHandlerContext ctx) {
        if (clmRequest != null) {
            String processUuid = clmRequest.getClientProcessUuid();
            Long current = System.currentTimeMillis();
            Long returnVal = lastHeartbeatMap.putIfAbsent(processUuid, current);
            Long lastBeat = lastHeartbeatMap.get(processUuid);
            // returnVal == null 表示是第一次，第一次可以破例进行处理
            if (current - lastBeat > IGNORE_TIME || returnVal == null) {
                lastHeartbeatMap.put(processUuid, lastBeat);

                // 遍历Map
                for (Map.Entry<String, Long> entry : lastHeartbeatMap.entrySet()) {
                    if (current - lastBeat > REMOVE_TIME) {
                        lastHeartbeatMap.remove(entry.getKey());
                    }
                }

                QueryClientProcess queryClientProcess = new QueryClientProcess();
                queryClientProcess.setProcessUuid(processUuid);
                ClientProcessDO clientProcessDO = clientProcessService.selectOneClientProcess(queryClientProcess);
                if (clientProcessDO != null) {
                    ClientProcessDO clientProcessDOForUpdate = new ClientProcessDO();
                    clientProcessDOForUpdate.setClientProcessId(clientProcessDO.getClientProcessId());
                    clientProcessDOForUpdate.setProcessLastBeatTime(new Date());
                    clientProcessService.updateClientProcessByClientProcessId(clientProcessDOForUpdate);
                } else {
                    // 可靠性处理，当没有找到记录时，服务端册通知客户端重新注册。
                    logger.error("Can't find any record by " + clmRequest.getContent());
                    ClmRequest<String> request = new ClmRequest<>();
                    request.setRequestId(clmRequest.getRequestId());
                    request.setEventName(EventEnum.clmReportSelfAgainEvent.name());
                    request.setContent(processUuid);
                    EventHelper.sendClmRequest(ctx, request);
                }
            }
        }
    }
}
